//
// Created by user on 20-3-13.
//
#include "Lib.h"

void listInit(List *list) {

    list->prev = list;
    list->next = list;
}

inline void listAddToBehind(List *entry, List *new) {

    new->next = entry->next;
    new->prev = entry;
    new->next->prev = new;

    entry->next = new;

}

void listAddToBefore(List *entry, List *new) {

    new->next = entry;
    entry->prev->next = new;

    new->prev = entry->prev;
    entry->prev = new;

}

List *listNext(List *entry) {

    if (entry->next != NULL)
        return entry->next;
    else
        return NULL;

}

inline long listIsEmpty(List *entry) {

    if (entry == entry->next && entry->prev == entry)
        return 1;
    else
        return 0;

}

inline void listDel(List *entry) {

    entry->next->prev = entry->prev;

    entry->prev->next = entry->next;

}

void *memset(void *address, unsigned char C, long Count) {

    int d0, d1;
    unsigned long tmp = C * 0x0101010101010101UL;

    __asm__ __volatile__    (
    "cld	\n\t"
            "rep	\n\t"
            "stosq	\n\t"
            "testb	$4, %b3	\n\t"
            "je	1f	\n\t"
            "stosl	\n\t"
            "1:\ttestb	$2, %b3	\n\t"
            "je	2f\n\t"
            "stosw	\n\t"
            "2:\ttestb	$1, %b3	\n\t"
            "je	3f	\n\t"
            "stosb	\n\t"
            "3:	\n\t"
    :"=&c"(d0), "=&D"(d1)
    :"a"(tmp), "q"(Count), "0"(Count / 8), "1"(address)
    :"memory"
    );

    return address;
}


void *memcpy(void *src, void *dest, long num) {

    int d0, d1, d2;

    __asm__ __volatile__    (    "cld	\n\t"
            "rep	\n\t"
            "movsq	\n\t"
            "testb	$4,%b4	\n\t"
            "je	1f	\n\t"
            "movsl	\n\t"
            "1:\ttestb	$2,%b4	\n\t"
            "je	2f	\n\t"
            "movsw	\n\t"
            "2:\ttestb	$1,%b4	\n\t"
            "je	3f	\n\t"
            "movsb	\n\t"
            "3:	\n\t"
    :"=&c"(d0), "=&D"(d1), "=&S"(d2)
    :"0"(num / 8), "q"(num), "1"(src), "2"(dest)
    :"memory"
    );

    return src;
}


int strlen(const char *String) {
    register int __res;

    __asm__ __volatile__    (
    "cld	\n\t"
            "repne	\n\t"
            "scasb	\n\t"
            "notl	%0	\n\t"
            "decl	%0	\n\t"
    :"=c"(__res)
    :"D"(String), "a"(0), "0"(0xffffffff)
    :
    );

    return __res;
}

unsigned char io_in8(unsigned short port) {

    unsigned char ret = 0;
    __asm__ __volatile__(    "inb	%%dx,	%0	\n\t"
            "mfence			\n\t"
    :"=a"(ret)
    :"d"(port)
    :"memory");
    return ret;
}

void io_out8(unsigned short port, unsigned char value) {

    __asm__ __volatile__(    "outb	%0,	%%dx	\n\t"
            "mfence			\n\t"
    :
    :"a"(value), "d"(port)
    :"memory");
}

inline unsigned int io_in32(unsigned short port) {

    unsigned int ret = 0;

    __asm__ __volatile__(    "inl	%%dx,	%0	\n\t"
            "mfence			\n\t"
    :"=a"(ret)
    :"d"(port)
    :"memory");

    return ret;
}

inline void io_out32(unsigned short port, unsigned int value) {

    __asm__ __volatile__(    "outl	%0,	%%dx	\n\t"
            "mfence			\n\t"
    :
    :"a"(value), "d"(port)
    :"memory");

}

inline unsigned long rdmsr(unsigned long address) {

    unsigned int tmp0 = 0;
    unsigned int tmp1 = 0;

    __asm__ __volatile__("rdmsr	\n\t":"=d"(tmp0), "=a"(tmp1):"c"(address):"memory");

    return (unsigned long) tmp0 << 32 | tmp1;
}

inline void wrmsr(unsigned long address, unsigned long value) {

    __asm__ __volatile__("wrmsr	\n\t"::"d"(value >> 32), "a"(value & 0xffffffff), "c"(address):"memory");

}

inline unsigned long getRFLAGS() {
    unsigned long tmp = 0;
    __asm__ __volatile__    ("pushfq	\n\t"
            "movq	(%%rsp), %0	\n\t"
            "popfq	\n\t"
    :"=r"(tmp)::"memory");
    return tmp;
}